ã€ãã¬ãŒã¿ãŒãã«ããŒã§JavaScriptã®ãªãœãŒã¹ç®¡çãæé©åãã¢ãã³JavaScriptæ©èœã§å ç¢ãã€å¹ççãªã¹ããªãŒã ãªãœãŒã¹ã·ã¹ãã ãæ§ç¯ã
JavaScript ã€ãã¬ãŒã¿ãŒãã«ã㌠ãªãœãŒã¹ãããŒãžã£ãŒïŒã¹ããªãŒã ãªãœãŒã¹ã·ã¹ãã
ã¢ãã³JavaScriptã¯ãããŒã¿ã¹ããªãŒã ããªãœãŒã¹ãå¹ççã«ç®¡çããããã®åŒ·åãªããŒã«ãæäŸããŸããã€ãã¬ãŒã¿ãŒãã«ããŒã¯ãéåæã€ãã¬ãŒã¿ãŒããžã§ãã¬ãŒã¿ãŒé¢æ°ãªã©ã®æ©èœãšçµã¿åãããããšã§ãéçºè ãå ç¢ã§ã¹ã±ãŒã©ãã«ãªã¹ããªãŒã ãªãœãŒã¹ã·ã¹ãã ãæ§ç¯ã§ããããã«ããŸãããã®èšäºã§ã¯ããããã®æ©èœãå©çšããŠããªãœãŒã¹ãå¹ççã«ç®¡çããããã©ãŒãã³ã¹ãæé©åããã³ãŒãã®å¯èªæ§ãåäžãããã·ã¹ãã ãæ§ç¯ããæ¹æ³ãæ¢ããŸãã
JavaScriptã«ããããªãœãŒã¹ç®¡çã®å¿ èŠæ§ã®çè§£
JavaScriptã¢ããªã±ãŒã·ã§ã³ãç¹ã«å€§èŠæš¡ãªããŒã¿ã»ãããå€éšAPIãæ±ãã¢ããªã±ãŒã·ã§ã³ã§ã¯ãå¹ççãªãªãœãŒã¹ç®¡çãäžå¯æ¬ ã§ãã管çãããŠããªããªãœãŒã¹ã¯ãããã©ãŒãã³ã¹ã®ããã«ããã¯ãã¡ã¢ãªãªãŒã¯ãããã³ãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã®äœäžã«ã€ãªããå¯èœæ§ããããŸãããªãœãŒã¹ç®¡çãéèŠãªäžè¬çãªã·ããªãªã«ã¯ã以äžã®ãããªãã®ããããŸãã
- å€§èŠæš¡ãã¡ã€ã«ã®åŠçïŒ å€§èŠæš¡ãã¡ã€ã«ãèªã¿èŸŒãã§åŠçãããç¹ã«ãã©ãŠã¶ãŒç°å¢ã§ã¯ãã¡ã€ã³ã¹ã¬ããããããã¯ããªãããã«æ³šææ·±ã管çãå¿ èŠã§ãã
- APIããã®ããŒã¿ã¹ããªãŒãã³ã°ïŒ å€§èŠæš¡ãªããŒã¿ã»ãããè¿ãAPIããããŒã¿ãååŸããå Žåã¯ãã¯ã©ã€ã¢ã³ããå§åããªãããã«ã¹ããªãŒãã³ã°æ¹åŒã§åŠçããå¿ èŠããããŸãã
- ããŒã¿ããŒã¹æ¥ç¶ã®ç®¡çïŒ ããŒã¿ããŒã¹æ¥ç¶ãå¹ççã«åŠçããããšã¯ãã¢ããªã±ãŒã·ã§ã³ã®å¿çæ§ãšã¹ã±ãŒã©ããªãã£ã確ä¿ããããã«äžå¯æ¬ ã§ãã
- ã€ãã³ãé§ååã·ã¹ãã ïŒ ã€ãã³ãã¹ããªãŒã ã管çããã€ãã³ããªã¹ããŒãé©åã«ã¯ãªãŒã³ã¢ãããããŠããããšã確èªããããšã¯ãã¡ã¢ãªãªãŒã¯ãé²ãããã«éèŠã§ãã
é©åã«èšèšããããªãœãŒã¹ç®¡çã·ã¹ãã ã¯ããªãœãŒã¹ãå¿ èŠãªãšãã«ååŸãããå¹ççã«äœ¿çšãããäžèŠã«ãªã£ããéããã«è§£æŸãããããšãä¿èšŒããŸããããã«ãããã¢ããªã±ãŒã·ã§ã³ã®ãããããªã³ããæå°éã«æããããããã©ãŒãã³ã¹ãåäžããå®å®æ§ãåäžããŸãã
ã€ãã¬ãŒã¿ãŒãã«ããŒã®ç޹ä»
ã€ãã¬ãŒã¿ãŒãã«ããŒïŒArray.prototype.values()ã¡ãœãããšãåŒã°ããïŒã¯ãã€ãã©ãã«ãªããŒã¿æ§é ãæäœããããã®åŒ·åãªæ¹æ³ãæäŸããŸãããããã®ã¡ãœããã¯ã€ãã¬ãŒã¿ãŒäžã§åäœãã宣èšçãã€å¹ççãªæ¹æ³ã§ããŒã¿ã倿ããã£ã«ã¿ãªã³ã°ãããã³æ¶è²»ããããšãã§ããŸããçŸåšãã¹ããŒãž4ã®ææ¡ã§ããããã¹ãŠã®ãã©ãŠã¶ãŒã§ãã€ãã£ãã«ãµããŒããããŠããããã§ã¯ãããŸããããããªãã£ã«ã䜿çšããããBabelã®ãããªãã©ã³ã¹ãã€ã©ãšçµã¿åãããŠäœ¿çšãããããããšãã§ããŸããæãäžè¬çã«äœ¿çšãããã€ãã¬ãŒã¿ãŒãã«ããŒã«ã¯ã以äžã®ãããªãã®ããããŸãã
map()ïŒã€ãã¬ãŒã¿ãŒã®åèŠçŽ ã倿ããŸããfilter()ïŒæå®ãããè¿°èªã«åºã¥ããŠèŠçŽ ããã£ã«ã¿ãªã³ã°ããŸããtake()ïŒæåã®nåã®èŠçŽ ãæã€æ°ããã€ãã¬ãŒã¿ãŒãè¿ããŸããdrop()ïŒæåã®nåã®èŠçŽ ãã¹ãããããæ°ããã€ãã¬ãŒã¿ãŒãè¿ããŸããreduce()ïŒã€ãã¬ãŒã¿ãŒã®å€ãåäžã®çµæã«éçŽããŸããforEach()ïŒæäŸããã颿°ãåèŠçŽ ã«å¯ŸããŠ1åå®è¡ããŸãã
ã€ãã¬ãŒã¿ãŒãã«ããŒã¯ãéåæããŒã¿ã¹ããªãŒã ãæäœããéã«ç¹ã«åœ¹ç«ã¡ãŸããããã¯ãããŒã¿ãé å»¶è©äŸ¡ã§åŠçã§ããããã§ããããã¯ãããŒã¿ãå¿ èŠãªãšãã«ã®ã¿åŠçãããããšãæå³ããç¹ã«å€§èŠæš¡ãªããŒã¿ã»ãããæ±ãå Žåã«ããã©ãŒãã³ã¹ãå€§å¹ ã«åäžããå¯èœæ§ããããŸãã
ã€ãã¬ãŒã¿ãŒãã«ããŒã䜿çšããã¹ããªãŒã ãªãœãŒã¹ã·ã¹ãã ã®æ§ç¯
ã€ãã¬ãŒã¿ãŒãã«ããŒã䜿çšããŠã¹ããªãŒã ãªãœãŒã¹ã·ã¹ãã ãæ§ç¯ããæ¹æ³ãæ€èšããŠã¿ãŸãããããã¡ã€ã«ã¹ããªãŒã ããã®ããŒã¿ã®èªã¿èŸŒã¿ãšã€ãã¬ãŒã¿ãŒãã«ããŒã䜿çšããåŠçã®åºæ¬çãªäŸããå§ããŸãã
äŸïŒãã¡ã€ã«ã¹ããªãŒã ã®èªã¿èŸŒã¿ãšåŠç
å€§èŠæš¡ãªãã¡ã€ã«ãèªã¿èŸŒã¿ãåè¡ãåŠçããç¹å®ã®æ å ±ãæœåºããå¿ èŠãããã·ããªãªãèããŠã¿ãŸããããåŸæ¥ã®ã¡ãœããã䜿çšãããšããã¡ã€ã«å šäœãã¡ã¢ãªã«ããŒãããããšã«ãªããéå¹ççã«ãªãå¯èœæ§ããããŸããã€ãã¬ãŒã¿ãŒãã«ããŒãšéåæã€ãã¬ãŒã¿ãŒã䜿çšãããšããã¡ã€ã«ã¹ããªãŒã ã1è¡ãã€åŠçã§ããŸãã
ãŸãããã¡ã€ã«ã¹ããªãŒã ã1è¡ãã€èªã¿åãéåæãžã§ãã¬ãŒã¿ãŒé¢æ°ãäœæããŸãã
async function* readFileLines(filePath) {
const fileStream = fs.createReadStream(filePath, { encoding: 'utf8' });
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
try {
for await (const line of rl) {
yield line;
}
} finally {
// ãšã©ãŒãçºçããå Žåã§ãããã¡ã€ã«ã¹ããªãŒã ã確å®ã«éããããããã«ããŸã
fileStream.destroy();
}
}
ãã®é¢æ°ã¯ãNode.jsã®fsããã³readlineã¢ãžã¥ãŒã«ã䜿çšããŠãèªã¿åãã¹ããªãŒã ãäœæãããã¡ã€ã«ã®åè¡ãå埩åŠçããŸããfinallyãããã¯ã¯ãèªã¿åãããã»ã¹äžã«ãšã©ãŒãçºçããå Žåã§ãããã¡ã€ã«ã¹ããªãŒã ãé©åã«éããããããšãä¿èšŒããŸããããã¯ãªãœãŒã¹ç®¡çã®éèŠãªéšåã§ãã
次ã«ãã€ãã¬ãŒã¿ãŒãã«ããŒã䜿çšããŠãã¡ã€ã«ã¹ããªãŒã ããã®è¡ãåŠçã§ããŸãã
async function processFile(filePath) {
const lines = readFileLines(filePath);
// ã€ãã¬ãŒã¿ãŒãã«ããŒã®ã·ãã¥ã¬ãŒã·ã§ã³
async function* map(iterable, transform) {
for await (const item of iterable) {
yield transform(item);
}
}
async function* filter(iterable, predicate) {
for await (const item of iterable) {
if (predicate(item)) {
yield item;
}
}
// "ã€ãã¬ãŒã¿ãŒãã«ããŒ"ïŒããã§ã¯ã·ãã¥ã¬ãŒã·ã§ã³ïŒã®äœ¿çš
const processedLines = map(filter(lines, line => line.length > 0), line => line.toUpperCase());
for await (const line of processedLines) {
console.log(line);
}
}
ãã®äŸã§ã¯ããŸã空ã®è¡ããã£ã«ã¿ãªã³ã°ãããã®åŸãæ®ãã®è¡ã倧æåã«å€æããŸãããããã®ã·ãã¥ã¬ãŒããããã€ãã¬ãŒã¿ãŒãã«ããŒé¢æ°ã¯ãã¹ããªãŒã ãé
å»¶è©äŸ¡ã§åŠçããæ¹æ³ã瀺ããŠããŸããfor await...ofã«ãŒãã¯ãåŠçãããè¡ãæ¶è²»ããããããã³ã³ãœãŒã«ã«åºåããŸãã
ãã®ã¢ãããŒãã®å©ç¹
- ã¡ã¢ãªå¹çïŒ ãã¡ã€ã«ã¯1è¡ãã€åŠçããããããå¿ èŠãªã¡ã¢ãªéãåæžãããŸãã
- ããã©ãŒãã³ã¹ã®åäžïŒ é å»¶è©äŸ¡ã«ãããå¿ èŠãªããŒã¿ã®ã¿ãåŠçãããããšãä¿èšŒãããŸãã
- ãªãœãŒã¹ã®å®å
šæ§ïŒ
finallyãããã¯ã¯ããšã©ãŒãçºçããå Žåã§ããã¡ã€ã«ã¹ããªãŒã ãé©åã«éããããããšãä¿èšŒããŸãã - å¯èªæ§ïŒ ã€ãã¬ãŒã¿ãŒãã«ããŒã¯ãè€éãªããŒã¿å€æã宣èšçã«è¡šçŸããæ¹æ³ãæäŸããŸãã
é«åºŠãªãªãœãŒã¹ç®¡çãã¯ããã¯
åºæ¬çãªãã¡ã€ã«åŠçãè¶ ããŠãã€ãã¬ãŒã¿ãŒãã«ããŒã䜿çšããŠãããé«åºŠãªãªãœãŒã¹ç®¡çãã¯ããã¯ãå®è£ ã§ããŸãã以äžã«ããã€ãã®äŸã瀺ããŸãã
1. ã¬ãŒãå¶é
å€éšAPIãšããåãããå ŽåãAPIã®äœ¿çšå¶éãè¶ ããªãããã«ãã¬ãŒãå¶éãå®è£ ããå¿ èŠãããããšããããããŸããã€ãã¬ãŒã¿ãŒãã«ããŒã䜿çšããŠãAPIãžã®ãªã¯ãšã¹ãéä¿¡ã¬ãŒããå¶åŸ¡ã§ããŸãã
async function* rateLimit(iterable, delay) {
for await (const item of iterable) {
yield item;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
async function* fetchFromAPI(urls) {
for (const url of urls) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
yield await response.json();
}
}
async function processAPIResponses(urls, rateLimitDelay) {
const apiResponses = fetchFromAPI(urls);
const rateLimitedResponses = rateLimit(apiResponses, rateLimitDelay);
for await (const response of rateLimitedResponses) {
console.log(response);
}
}
// 䜿çšäŸ:
const apiUrls = [
'https://api.example.com/data1',
'https://api.example.com/data2',
'https://api.example.com/data3'
];
// ãªã¯ãšã¹ãéã®ã¬ãŒãå¶éã500msã«èšå®
await processAPIResponses(apiUrls, 500);
ãã®äŸã§ã¯ãrateLimit颿°ã¯ãã€ãã©ãã«ããæŸåºãããåã¢ã€ãã ã®éã«é
å»¶ãå°å
¥ããŸããããã«ãããAPIãªã¯ãšã¹ããå¶åŸ¡ãããã¬ãŒãã§éä¿¡ãããããšãä¿èšŒãããŸããfetchFromAPI颿°ã¯ãæå®ãããURLããããŒã¿ãååŸããJSONã¬ã¹ãã³ã¹ãyieldããŸããprocessAPIResponsesã¯ãããã®é¢æ°ãçµã¿åãããŠãã¬ãŒãå¶éä»ãã§APIã¬ã¹ãã³ã¹ãååŸããã³åŠçããŸããé©åãªãšã©ãŒåŠçïŒäŸïŒresponse.okã®ãã§ãã¯ïŒãå«ãŸããŠããŸãã
2. ãªãœãŒã¹ããŒãªã³ã°
ãªãœãŒã¹ããŒãªã³ã°ã¯ããªãœãŒã¹ã®äœæãšç Žæ£ã®ãªãŒããŒããããç¹°ãè¿ãåé¿ããããã«ãåå©çšå¯èœãªãªãœãŒã¹ã®ããŒã«ãäœæããããšãå«ã¿ãŸããã€ãã¬ãŒã¿ãŒãã«ããŒã䜿çšããŠãããŒã«ããã®ãªãœãŒã¹ã®ååŸãšè§£æŸã管çã§ããŸãã
ãã®äŸã¯ãããŒã¿ããŒã¹æ¥ç¶ã®ããã®åçŽåããããªãœãŒã¹ããŒã«ã瀺ããŠããŸãã
class ConnectionPool {
constructor(size, createConnection) {
this.size = size;
this.createConnection = createConnection;
this.pool = [];
this.available = [];
this.initializePool();
}
async initializePool() {
for (let i = 0; i < this.size; i++) {
const connection = await this.createConnection();
this.pool.push(connection);
this.available.push(connection);
}
}
async acquire() {
if (this.available.length > 0) {
return this.available.pop();
}
// å©çšå¯èœãªæ¥ç¶ããªãå Žåã®åŠçããªãã·ã§ã³ã§åŠçããŸããäŸïŒåŸ
æ©ãŸãã¯ãšã©ãŒãã¹ããŒããŸãã
throw new Error("No available connections in the pool.");
}
release(connection) {
this.available.push(connection);
}
async useConnection(callback) {
const connection = await this.acquire();
try {
return await callback(connection);
} finally {
this.release(connection);
}
}
}
// 䜿çšäŸïŒããŒã¿ããŒã¹æ¥ç¶ãäœæãã颿°ãããããšãåæãšããŸãïŒ
async function createDBConnection() {
// ããŒã¿ããŒã¹æ¥ç¶ã®äœæãã·ãã¥ã¬ãŒãããŸã
return new Promise(resolve => {
setTimeout(() => {
resolve({ id: Math.random(), query: (sql) => Promise.resolve(`Executed: ${sql}`) }); // æ¥ç¶ãªããžã§ã¯ããã·ãã¥ã¬ãŒã
}, 100);
});
}
async function main() {
const poolSize = 5;
const pool = new ConnectionPool(poolSize, createDBConnection);
// ããŒã«ãåæåãããã®ãåŸ
ã¡ãŸã
await new Promise(resolve => setTimeout(resolve, 100 * poolSize));
// æ¥ç¶ããŒã«ã䜿çšããŠã¯ãšãªãå®è¡ããŸã
for (let i = 0; i < 10; i++) {
try {
const result = await pool.useConnection(async (connection) => {
return await connection.query(`SELECT * FROM users WHERE id = ${i}`);
});
console.log(`Query ${i} Result: ${result}`);
} catch (error) {
console.error(`Error executing query ${i}: ${error.message}`);
}
}
}
main();
ãã®äŸã§ã¯ãConnectionPoolã¯ã©ã¹ãå®çŸ©ããŠãããããŒã¿ããŒã¹æ¥ç¶ã®ããŒã«ã管çããŸããacquireã¡ãœããã¯ããŒã«ããæ¥ç¶ãååŸããreleaseã¡ãœããã¯æ¥ç¶ãããŒã«ã«æ»ããŸããuseConnectionã¡ãœããã¯æ¥ç¶ãååŸããæ¥ç¶ã䜿çšããŠã³ãŒã«ããã¯é¢æ°ãå®è¡ãããã®åŸæ¥ç¶ãè§£æŸããŸããããã«ãããæ¥ç¶ãåžžã«ããŒã«ã«æ»ãããããšãä¿èšŒãããŸãããã®ã¢ãããŒãã¯ãããŒã¿ããŒã¹ãªãœãŒã¹ã®å¹æçãªäœ¿çšãä¿é²ããæ°ããæ¥ç¶ãç¹°ãè¿ãäœæãããªãŒããŒããããåé¿ããŸãã
3. ã¹ããããªã³ã°
ã¹ããããªã³ã°ã¯ãã·ã¹ãã ãå§åããªãããã«ãåææäœã®æ°ãå¶éããŸããã€ãã¬ãŒã¿ãŒãã«ããŒã䜿çšããŠãéåæã¿ã¹ã¯ã®å®è¡ãã¹ãããã«ã§ããŸãã
async function* throttle(iterable, concurrency) {
const queue = [];
let running = 0;
let iterator = iterable[Symbol.asyncIterator]();
async function execute() {
if (queue.length === 0 || running >= concurrency) {
return;
}
running++;
const { value, done } = queue.shift();
try {
yield await value;
} finally {
running--;
if (!done) {
execute(); // å®äºããŠããªãå Žåã¯åŠçãç¶è¡ããŸã
}
}
if (queue.length > 0) {
execute(); // å©çšå¯èœãªå Žåã¯å¥ã®ã¿ã¹ã¯ãéå§ããŸã
}
}
async function fillQueue() {
while (running < concurrency) {
const { value, done } = await iterator.next();
if (done) {
return;
}
queue.push({ value, done });
execute();
}
}
await fillQueue();
}
async function* generateTasks(count) {
for (let i = 1; i <= count; i++) {
yield new Promise(resolve => {
const delay = Math.random() * 1000;
setTimeout(() => {
console.log(`Task ${i} completed after ${delay}ms`);
resolve(`Result from task ${i}`);
}, delay);
});
}
}
async function main() {
const taskCount = 10;
const concurrencyLimit = 3;
const tasks = generateTasks(taskCount);
const throttledTasks = throttle(tasks, concurrencyLimit);
for await (const result of throttledTasks) {
console.log(`Received: ${result}`);
}
console.log('All tasks completed');
}
main();
ãã®äŸã§ã¯ãthrottle颿°ãéåæã¿ã¹ã¯ã®åæå®è¡æ°ãå¶éããŸããä¿çäžã®ã¿ã¹ã¯ã®ãã¥ãŒãç¶æããæå®ãããåæå®è¡å¶éãŸã§ããããå®è¡ããŸããgenerateTasks颿°ã¯ãã©ã³ãã ãªé
å»¶åŸã«è§£æ±ºãããäžé£ã®éåæã¿ã¹ã¯ãäœæããŸããmain颿°ã¯ãããã®é¢æ°ãçµã¿åãããŠãã¹ããããªã³ã°ã䜿çšããŠã¿ã¹ã¯ãå®è¡ããŸããããã«ãããã·ã¹ãã ãéå°ãªåææäœã§å§åãããªãããšãä¿èšŒãããŸãã
ãšã©ãŒãã³ããªã³ã°
å
ç¢ãªãšã©ãŒãã³ããªã³ã°ã¯ããããããªãœãŒã¹ç®¡çã·ã¹ãã ã®äžå¯æ¬ ãªéšåã§ããéåæããŒã¿ã¹ããªãŒã ãæ±ãå ŽåããªãœãŒã¹ãªãŒã¯ãé²ããã¢ããªã±ãŒã·ã§ã³ã®å®å®æ§ã確ä¿ããããã«ããšã©ãŒãé©åã«åŠçããããšãéèŠã§ããtry-catch-finallyãããã¯ã䜿çšããŠããšã©ãŒãçºçããå Žåã§ããªãœãŒã¹ãé©åã«ã¯ãªãŒã³ã¢ãããããããšã確èªããŠãã ããã
ããšãã°ãäžèšã®readFileLines颿°ã§ã¯ãfinallyãããã¯ã«ãããèªã¿åãããã»ã¹äžã«ãšã©ãŒãçºçããå Žåã§ãããã¡ã€ã«ã¹ããªãŒã ãéããããããšãä¿èšŒãããŸãã
çµè«
JavaScriptã€ãã¬ãŒã¿ãŒãã«ããŒã¯ãéåæããŒã¿ã¹ããªãŒã ã®ãªãœãŒã¹ã管çããããã®åŒ·åã§å¹ççãªæ¹æ³ãæäŸããŸããã€ãã¬ãŒã¿ãŒãã«ããŒãéåæã€ãã¬ãŒã¿ãŒããžã§ãã¬ãŒã¿ãŒé¢æ°ãªã©ã®æ©èœãšçµã¿åãããããšã§ãéçºè ã¯å ç¢ã§ã¹ã±ãŒã©ãã«ã§ä¿å®å¯èœãªã¹ããªãŒã ãªãœãŒã¹ã·ã¹ãã ãæ§ç¯ã§ããŸããé©åãªãªãœãŒã¹ç®¡çã¯ãç¹ã«å€§èŠæš¡ãªããŒã¿ã»ãããå€éšAPIãæ±ãJavaScriptã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ãå®å®æ§ãããã³ä¿¡é Œæ§ã確ä¿ããããã«äžå¯æ¬ ã§ããã¬ãŒãå¶éããªãœãŒã¹ããŒãªã³ã°ãããã³ã¹ããããªã³ã°ãªã©ã®ãã¯ããã¯ãå®è£ ããããšã§ããªãœãŒã¹ã®äœ¿çšãæé©åããããã«ããã¯ãé²ããå šäœçãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãåäžãããããšãã§ããŸãã